package com.iwhalecloud.bss.kite.cucc.order.accept.chain.impl;

import com.google.common.collect.Sets;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.constant.TableConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.order.accept.chain.AbstractOrderHandler;
import com.iwhalecloud.bss.kite.cucc.order.accept.constructor.DataConstructorFactory;
import com.iwhalecloud.bss.kite.cucc.order.accept.constructor.IDataConstructor;
import com.iwhalecloud.bss.kite.cucc.order.accept.constructor.inst.RelConstructor;
import com.iwhalecloud.bss.kite.cucc.order.loader.InstLoaderFactory;
import com.iwhalecloud.bss.kite.cucc.order.loader.impl.InstLoader;
import com.iwhalecloud.bss.kite.cucc.order.util.AcceptUtils;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.IInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInstAttr;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferObjInstRel;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferProdInstRel;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInstFunc;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInstFuncExt;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInstRel;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.OfferObjInstRelMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.OfferProdInstRelMapper;
import com.iwhalecloud.bss.kite.dataservice.mapper.inst.ProdInstRelMapper;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.enums.RelType;
import com.iwhalecloud.bss.kite.manager.inst.KiteInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteMktResInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInstAssure;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInstAcct;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInstFunc;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInstState;
import com.iwhalecloud.bss.kite.manager.inst.KiteSubProdInst;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteRelChange;
import com.iwhalecloud.bss.kite.manager.inst.graph.IRelType;
import com.iwhalecloud.bss.kite.manager.inst.graph.impl.RelEdge;
import com.iwhalecloud.bss.kite.manager.util.ManagerUtils;
import com.iwhalecloud.bss.kite.manager.util.RelTypeUtils;
import com.iwhalecloud.bss.kite.order.client.dto.InstContainer;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.iwhalecloud.bss.kite.order.client.proxy.InstContainerProxy;
import com.ztesoft.bss.base.staticdata.CoreDataOffer;
import com.ztesoft.bss.common.util.SpringUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 订单受理流程：实例过户处理
 */
@Component
public class TransferHandler extends AbstractOrderHandler {

    @Override
    public boolean canHandle(OrderRequest orderRequest) {
        if (Objects.isNull(orderRequest) || !(isTransferServiceOffer(orderRequest.getServiceOfferId())
            && StringUtils.isNotBlank(orderRequest.getNewCustId()))) {
            return false;
        }

        return true;
    }

    @Override
    public void doHandle(OrderRequest orderRequest) {
        // 补充newOwnerCustId变动信息的oldValue
        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        orderRequest.getInstChangeMap().forEach((key, instChanges) -> {
            instChanges.forEach(instChange -> {
                if (!(Objects.equals(KiteInst.NEW_OWNER_CUST_ID, instChange.getFieldName())
                    && StringUtils.isBlank(instChange.getOldValue()))) {
                    return;
                }

                KiteInst inst = querySceneInstService.getKiteInst(orderRequest.getCustId(), instChange.getSubInstType(),
                    instChange.getSubInstId());
                if (Objects.nonNull(inst)) {
                    instChange.setOldValue(inst.getOwnerCustId());
                }
            });
        });

        InstContainerProxy instContainer = InstContainer.ofRequest(orderRequest);
        List<OfferInst> offerInsts = instContainer.listOfferInsts();
        List<ProdInst> prodInsts = instContainer.listProdInsts();

        offerInsts = fillAdditionalOfferInsts(orderRequest, offerInsts, prodInsts);
        transferOfferInsts(orderRequest, offerInsts);
        transferProdInsts(orderRequest, prodInsts);
    }

    /**
     * 判断是否过户相关的服务提供
     * @param serviceOfferId
     * @return
     */
    private boolean isTransferServiceOffer(String serviceOfferId) {
        if (StringUtils.isBlank(serviceOfferId)) {
            return false;
        }

        return Sets.newHashSet(ServiceOfferConsts.SERVICE_OFFER_TRANSFER, ServiceOfferConsts.SERVICE_OFFER_MERGE,
            ServiceOfferConsts.SERVICE_OFFER_CUST_RETURN).contains(serviceOfferId);
    }

    /**
     * 销售品实例过户
     * @param orderRequest
     * @param offerInsts
     */
    private void transferOfferInsts(OrderRequest orderRequest, List<OfferInst> offerInsts) {
        if (Objects.isNull(orderRequest) || CollectionUtils.isEmpty(offerInsts)) {
            return;
        }

        for (OfferInst offerInst : offerInsts) {
            String offerInstId = offerInst.getOfferInstId();
            String offerType = offerInst.getOfferType();
            String ownerCustId = offerInst.getOwnerCustId();
            String newOwnerCustId = offerInst.getNewOwnerCustId();
            if (StringUtils.isBlank(newOwnerCustId) || KiteStringUtils.equals(ownerCustId, newOwnerCustId)) {
                continue;
            }

            if (Objects.equals(CoreDataOffer.OFF_0005_10, offerType)) {
                // 补充基础销售品newOwnerCustId的变动信息
                InstType instType = AcceptUtils.getOfferInstType(offerType);
                AcceptUtils.addInstChange(orderRequest, offerInstId, instType, ActionType.M, KiteInst.NEW_OWNER_CUST_ID,
                    offerInst.getOwnerCustId(), offerInst.getNewOwnerCustId());
            }

            // 销售品实例属性
            transferOfferInstAttrs(orderRequest, offerInstId, newOwnerCustId);

            // 过户时销售品包含对象实例要一起过
            List<OfferObjInstRel> offerObjInstRels = listOfferObjInstRels(offerInstId, ownerCustId);
            for (OfferObjInstRel offerObjInstRel : offerObjInstRels) {
                if (KiteStringUtils.equals(newOwnerCustId, offerObjInstRel.getOwnerCustId())) {
                    continue;
                }

                RelEdge relEdge = createOfferObjInstRelEdge(offerObjInstRel, offerType);
                transferInstRel(orderRequest, offerObjInstRel, TableConsts.OfferObjInstRel.getTableName(),
                    offerObjInstRel.getOfferObjInstRelId(), newOwnerCustId, relEdge);
            }

            // 销售品实例和功能产品实例关系
            List<OfferProdInstRel> offerProdInstRels = listOfferProdInstRels(offerInstId, ownerCustId);
            for (OfferProdInstRel offerProdInstRel : offerProdInstRels) {
                if (KiteStringUtils.equals(newOwnerCustId, offerProdInstRel.getOwnerCustId())) {
                    continue;
                }

                RelEdge relEdge = createOfferProdInstRelEdge(offerProdInstRel, offerType);
                transferInstRel(orderRequest, offerProdInstRel, TableConsts.OfferProdInstRel.getTableName(),
                    offerProdInstRel.getOfferProdInstRelId(), newOwnerCustId, relEdge);
            }
        }
    }

    /**
     * 接入产品实例过户
     * @param orderRequest
     * @param prodInsts
     */
    private void transferProdInsts(OrderRequest orderRequest, List<ProdInst> prodInsts) {
        if (Objects.isNull(orderRequest) || CollectionUtils.isEmpty(prodInsts)) {
            return;
        }

        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        for (ProdInst prodInst : prodInsts) {
            String prodInstId = prodInst.getProdInstId();
            String ownerCustId = prodInst.getOwnerCustId();
            String newOwnerCustId = prodInst.getNewOwnerCustId();
            if (StringUtils.isBlank(newOwnerCustId) || KiteStringUtils.equals(ownerCustId, newOwnerCustId)) {
                continue;
            }

            // 功能产品实例
            List<KiteProdInstFunc> prodInstFuncs = querySceneInstService.listProdInstFuncs(ownerCustId, prodInstId);
            transferInsts(orderRequest, prodInst, prodInstFuncs, TableConsts.ProdInstFunc.getTableName());
            // 功能产品实例属性
            transferProdInstFuncExts(orderRequest, prodInstId, newOwnerCustId);

            // 终端实例
            List<KiteMktResInst> mktResInsts = querySceneInstService.listMktResInstsByProdInstId(ownerCustId,
                prodInstId);
            transferInsts(orderRequest, prodInst, mktResInsts, TableConsts.OfferResInstRelExt.getTableName());

            // 账户实例
            List<KiteProdInstAcct> prodInstAccts = querySceneInstService.listProdInstAccts(ownerCustId, prodInstId);
            transferInsts(orderRequest, prodInst, prodInstAccts, TableConsts.ProdInstAcctRel.getTableName());

            // 停机记录
            List<KiteProdInstState> prodInstStates = querySceneInstService.listProdInstStates(ownerCustId, prodInstId);
            transferInsts(orderRequest, prodInst, prodInstStates, TableConsts.ProdInstState.getTableName());

            // 担保信息
            List<KiteOfferInstAssure> offerInstAssures = querySceneInstService.listOfferInstAssures(ownerCustId,
                prodInstId);
            transferInsts(orderRequest, prodInst, offerInstAssures, TableConsts.OfferInstAssureExt.getTableName());

            // 子产品实例
            List<KiteSubProdInst> subProdInsts = querySceneInstService.listSubProdInsts(ownerCustId, prodInstId);
            transferInsts(orderRequest, prodInst, subProdInsts, TableConsts.SubProdInst.getTableName());

            // 产品实例关系
            List<ProdInstRel> prodInstRels = listProdInstRels(prodInstId, ownerCustId);
            for (ProdInstRel prodInstRel : prodInstRels) {
                if (KiteStringUtils.equals(newOwnerCustId, prodInstRel.getOwnerCustId())) {
                    continue;
                }

                RelEdge relEdge = createProdInstRelEdge(prodInstRel, InstType.PROD_INST);
                transferInstRel(orderRequest, prodInstRel, TableConsts.ProdInstRel.getTableName(),
                    prodInstRel.getProdInstRelId(), newOwnerCustId, relEdge);
            }

            // 功能产品实例和接入产品实例群组关系(A端是功能产品实例，Z端是接入产品实例)
            for (KiteProdInstFunc prodInstFunc : prodInstFuncs) {
                if (!AcceptUtils.isGroupProdInstFunc(prodInstFunc)) {
                    continue;
                }

                prodInstRels = listProdInstRels(prodInstFunc.getProdInstId(), ownerCustId);
                for (ProdInstRel prodInstRel : prodInstRels) {
                    if (KiteStringUtils.equals(newOwnerCustId, prodInstRel.getOwnerCustId())) {
                        continue;
                    }

                    RelEdge relEdge = createProdInstRelEdge(prodInstRel, InstType.PROD_INST_FUNC);
                    transferInstRel(orderRequest, prodInstRel, TableConsts.ProdInstRel.getTableName(),
                        prodInstRel.getProdInstRelId(), newOwnerCustId, relEdge);
                }
            }
        }
    }

    /**
     * 往offerInsts列表补充销售品实例和接入产品实例的下级可选包销售品实例
     * @param orderRequest
     * @param offerInsts
     * @param prodInsts
     * @return
     */
    private List<OfferInst> fillAdditionalOfferInsts(OrderRequest orderRequest, List<OfferInst> offerInsts,
        List<ProdInst> prodInsts) {
        List<KiteOfferInst> kiteAdditionalOfferInsts = new ArrayList<>();
        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        if (CollectionUtils.isNotEmpty(offerInsts)) {
            for (OfferInst offerInst : offerInsts) {
                String offerInstId = offerInst.getOfferInstId();
                String offerType = offerInst.getOfferType();
                String ownerCustId = offerInst.getOwnerCustId();
                String newOwnerCustId = offerInst.getNewOwnerCustId();
                if (StringUtils.isBlank(newOwnerCustId) || KiteStringUtils.equals(ownerCustId, newOwnerCustId)) {
                    continue;
                }

                if (Objects.equals(CoreDataOffer.OFF_0005_10, offerType)
                    || Objects.equals(CoreDataOffer.OFF_0005_12, offerType)) {
                    continue;
                }

                // 获取销售品实例下的所有可选包销售品实例
                List<KiteOfferInst> kiteAdditionalOfferInstList = querySceneInstService
                    .listAdditionalOfferInstsFromOfferInst(ownerCustId, offerInstId);
                for (KiteOfferInst kiteAdditionalOfferInst : kiteAdditionalOfferInstList) {
                    kiteAdditionalOfferInst.setNewOwnerCustId(newOwnerCustId);
                    kiteAdditionalOfferInsts.add(kiteAdditionalOfferInst);
                }
            }
        }

        if (CollectionUtils.isNotEmpty(prodInsts)) {
            for (ProdInst prodInst : prodInsts) {
                String prodInstId = prodInst.getProdInstId();
                String ownerCustId = prodInst.getOwnerCustId();
                String newOwnerCustId = prodInst.getNewOwnerCustId();
                if (StringUtils.isBlank(newOwnerCustId) || KiteStringUtils.equals(ownerCustId, newOwnerCustId)) {
                    continue;
                }

                // 获取接入产品实例的所有可选包销售品实例
                List<KiteOfferInst> kiteAdditionalOfferInstList = querySceneInstService
                    .listAdditionalOfferInstsFromProdInst(ownerCustId, prodInstId);
                for (KiteOfferInst kiteAdditionalOfferInst : kiteAdditionalOfferInstList) {
                    kiteAdditionalOfferInst.setNewOwnerCustId(newOwnerCustId);
                    kiteAdditionalOfferInsts.add(kiteAdditionalOfferInst);
                }
            }
        }

        List<OfferInst> additionalOfferInsts = new ArrayList<>();
        String tableName = TableConsts.OfferInst.getTableName();
        InstLoader<OfferInst> instLoader = InstLoaderFactory.getInstLoader(tableName);
        for (KiteOfferInst kiteAdditionalOfferInst : kiteAdditionalOfferInsts) {
            String offerInstId = kiteAdditionalOfferInst.getOfferInstId();
            String ownerCustId = kiteAdditionalOfferInst.getOwnerCustId();
            String newOwnerCustId = kiteAdditionalOfferInst.getNewOwnerCustId();
            OfferInst additionalOfferInst = InstContainer.ofRequest(orderRequest).getOfferInst(offerInstId);
            if (Objects.isNull(additionalOfferInst)) {
                additionalOfferInst = instLoader.loadInst(orderRequest, tableName, offerInstId, ownerCustId);
                if (Objects.nonNull(additionalOfferInst)) {
                    additionalOfferInsts.add(additionalOfferInst);
                }
            }

            if (Objects.nonNull(additionalOfferInst)) {
                additionalOfferInst.setNewOwnerCustId(newOwnerCustId);
            }
        }

        if (Objects.nonNull(offerInsts)) {
            offerInsts.addAll(additionalOfferInsts);
        }
        else {
            offerInsts = additionalOfferInsts;
        }

        return offerInsts;
    }

    /**
     * 销售品实例属性过户
     * @param orderRequest
     * @param offerInstId
     * @param newOwnerCustId
     */
    private void transferOfferInstAttrs(OrderRequest orderRequest, String offerInstId, String newOwnerCustId) {
        if (Objects.isNull(orderRequest) || StringUtils.isAnyBlank(offerInstId, newOwnerCustId)) {
            return;
        }

        List<OfferInstAttr> offerInstAttrs = InstContainer.ofRequest(orderRequest).listOfferInstAttrs(offerInstId);
        for (OfferInstAttr offerInstAttr : offerInstAttrs) {
            if (AcceptUtils.isAddInst(offerInstAttr)) {
                offerInstAttr.setOwnerCustId(newOwnerCustId);
                offerInstAttr.setNewOwnerCustId(null);
                continue;
            }

            if (!KiteStringUtils.equals(newOwnerCustId, offerInstAttr.getOwnerCustId())) {
                offerInstAttr.setNewOwnerCustId(newOwnerCustId);
                if (StringUtils.equalsAny(offerInstAttr.getActionType(), ActionType.A.name(), ActionType.K.name())) {
                    AcceptUtils.setActionType(offerInstAttr, ActionType.M.name());
                }
            }
        }
    }

    /**
     * 根据销售实例id查询销售品包含对象实例
     * @param offerInstId
     * @param custId
     * @return
     */
    private List<OfferObjInstRel> listOfferObjInstRels(String offerInstId, String custId) {
        if (StringUtils.isAnyBlank(offerInstId, custId)) {
            return new ArrayList<>();
        }

        Example example = new Example(OfferObjInstRel.class);
        example.createCriteria().andEqualTo("offerInstId", offerInstId).andEqualTo("ownerCustId", custId);
        OfferObjInstRelMapper mapper = SpringUtil.getBean(OfferObjInstRelMapper.class);
        List<OfferObjInstRel> offerObjInstRels = mapper.selectByExample(example);
        for (OfferObjInstRel offerObjInstRel : offerObjInstRels) {
            if (Objects.equals(ActionType.A.name(), offerObjInstRel.getActionType())) {
                offerObjInstRel.setNewActionType(ActionType.K.name());
            }
        }
        return offerObjInstRels;
    }

    /**
     * 根据销售品实例id查询销售品产品实例关系
     * @param offerInstId
     * @param custId
     * @return
     */
    private List<OfferProdInstRel> listOfferProdInstRels(String offerInstId, String custId) {
        if (StringUtils.isAnyBlank(offerInstId, custId)) {
            return new ArrayList<>();
        }

        Example example = new Example(OfferProdInstRel.class);
        example.createCriteria().andEqualTo("offerInstId", offerInstId).andEqualTo("ownerCustId", custId);
        OfferProdInstRelMapper mapper = SpringUtil.getBean(OfferProdInstRelMapper.class);
        List<OfferProdInstRel> offerProdInstRels = mapper.selectByExample(example);
        for (OfferProdInstRel offerProdInstRel : offerProdInstRels) {
            if (Objects.equals(ActionType.A.name(), offerProdInstRel.getActionType())) {
                offerProdInstRel.setNewActionType(ActionType.K.name());
            }
        }
        return offerProdInstRels;
    }

    /**
     * 关系实例过户
     * @param orderRequest
     * @param inst
     * @param tableName
     * @param instId
     * @param newOwnerCustId
     * @param relEdge
     */
    private void transferInstRel(OrderRequest orderRequest, IInst inst, String tableName, String instId,
        String newOwnerCustId, RelEdge relEdge) {
        if (!ObjectUtils.allNotNull(orderRequest, inst) || StringUtils.isAnyBlank(tableName, instId, newOwnerCustId)) {
            return;
        }

        String oldActionType = inst.getActionType();
        InstContainerProxy instContainer = InstContainer.ofRequest(orderRequest);
        IInst instRel = instContainer.getInst(tableName, instId);
        if (Objects.isNull(instRel)) {
            if (StringUtils.equalsAny(oldActionType, ActionType.A.name(), ActionType.K.name())) {
                AcceptUtils.setActionType(inst, ActionType.M.name());
            }
            inst.setNewOwnerCustId(newOwnerCustId);
            instContainer.addInst(inst);

            // 补充newOwnerCustId的变动信息
            addRelChange(orderRequest, relEdge, KiteInst.NEW_OWNER_CUST_ID, inst.getOwnerCustId(),
                inst.getNewOwnerCustId());
        }
        else if (StringUtils.isBlank(instRel.getNewOwnerCustId())) {
            if (StringUtils.equalsAny(instRel.getActionType(), ActionType.A.name(), ActionType.K.name())) {
                AcceptUtils.setActionType(instRel, ActionType.M.name());
            }
            instRel.setNewOwnerCustId(newOwnerCustId);

            // 补充newOwnerCustId的变动信息
            addRelChange(orderRequest, relEdge, KiteInst.NEW_OWNER_CUST_ID, instRel.getOwnerCustId(),
                instRel.getNewOwnerCustId());
        }
    }

    /**
     * 添加关系变动信息(如果没有则新增，否则更新newValue的值)
     * @param orderRequest
     * @param relEdge
     * @param fieldName
     * @param oldValue
     * @param newValue
     */
    private void addRelChange(OrderRequest orderRequest, RelEdge relEdge, String fieldName, String oldValue,
        String newValue) {
        KiteRelChange relChange = createRelChange(relEdge, fieldName, oldValue, newValue);
        if (Objects.nonNull(relChange)) {
            String key = ManagerUtils.join(relChange.getSourceInstType(), relChange.getSourceInstId());
            List<KiteRelChange> relChanges = orderRequest.getRelChangeMap().get(key);
            KiteRelChange change = RelConstructor.getRelChange(relChanges, relChange);
            if (Objects.isNull(change)) {
                orderRequest.getRelChangeMap().computeIfAbsent(key, k -> new ArrayList<>()).add(relChange);
            }
            else if (!KiteStringUtils.equals(newValue, change.getNewValue())) {
                change.setNewValue(newValue);
            }
        }
    }

    /**
     * 创建关系变动信息
     * @param relEdge
     * @param fieldName
     * @param oldValue
     * @param newValue
     * @return
     */
    private KiteRelChange createRelChange(RelEdge relEdge, String fieldName, String oldValue, String newValue) {
        if (Objects.isNull(relEdge) || StringUtils.isBlank(fieldName)) {
            return null;
        }

        KiteRelChange relChange = KiteBeanUtils.transform(relEdge, KiteRelChange.class);
        relChange.setFieldName(fieldName);
        relChange.setOldValue(oldValue);
        relChange.setNewValue(newValue);

        return relChange;
    }

    /**
     * 根据销售品包含对象实例创建关系边
     * @param offerObjInstRel
     * @param offerType
     * @return
     */
    private RelEdge createOfferObjInstRelEdge(OfferObjInstRel offerObjInstRel, String offerType) {
        if (Objects.isNull(offerObjInstRel)) {
            return null;
        }

        String targetInstId = offerObjInstRel.getObjId();
        InstType targetInstType = null;
        IRelType relType = RelTypeUtils.getRelType(RelType.OFFER_OBJ_REL_TYPE, offerObjInstRel.getObjType());
        if (Objects.equals(RelType.OFFER_OBJ_REL_TYPE_1000, relType)) {
            targetInstType = InstType.PROD_INST;
        }
        else if (Objects.equals(RelType.OFFER_OBJ_REL_TYPE_110000, relType)) {
            IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
            KiteOfferInst offerInst = querySceneInstService.getOfferInst(offerObjInstRel.getOwnerCustId(),
                targetInstId);
            targetInstType = Optional.ofNullable(offerInst).map(KiteOfferInst::getInstType).orElse(null);
        }
        else if (Objects.equals(RelType.OFFER_OBJ_REL_TYPE_170000, relType)) {
            targetInstType = InstType.OFFER_INST_ACCT;
        }

        RelEdge relEdge = new RelEdge();
        relEdge.setSourceInstId(offerObjInstRel.getOfferInstId());
        relEdge.setSourceInstType(AcceptUtils.getOfferInstType(offerType));
        relEdge.setTargetInstId(targetInstId);
        relEdge.setTargetInstType(targetInstType);
        relEdge.setRelType(relType);
        relEdge.setRoleId(offerObjInstRel.getProdCompRoleCd());
        relEdge.setDetailId(offerObjInstRel.getDetailId());

        return relEdge;
    }

    /**
     * 根据销售品产品实例关系创建关系边
     * @param offerProdInstRel
     * @param offerType
     * @return
     */
    private RelEdge createOfferProdInstRelEdge(OfferProdInstRel offerProdInstRel, String offerType) {
        if (Objects.isNull(offerProdInstRel)) {
            return null;
        }

        IRelType relType = RelTypeUtils.getRelType(RelType.OFFER_PROD_REL_TYPE, offerProdInstRel.getRelType());
        RelEdge relEdge = new RelEdge();
        relEdge.setSourceInstId(offerProdInstRel.getOfferInstId());
        relEdge.setSourceInstType(AcceptUtils.getOfferInstType(offerType));
        relEdge.setTargetInstId(offerProdInstRel.getProdInstId());
        relEdge.setTargetInstType(InstType.PROD_INST_FUNC);
        relEdge.setRelType(relType);
        relEdge.setRoleId(offerProdInstRel.getRoleId());
        relEdge.setDetailId(offerProdInstRel.getDetailId());

        return relEdge;
    }

    /**
     * 实例过户
     * @param orderRequest
     * @param prodInst
     * @param kiteInsts
     * @param tableName
     */
    private void transferInsts(OrderRequest orderRequest, ProdInst prodInst, List<? extends KiteInst> kiteInsts,
        String tableName) {
        if (!ObjectUtils.allNotNull(orderRequest, prodInst) || CollectionUtils.isEmpty(kiteInsts)
            || StringUtils.isBlank(tableName) || StringUtils.isBlank(prodInst.getNewOwnerCustId())
            || Objects.equals(prodInst.getOwnerCustId(), prodInst.getNewOwnerCustId())) {
            return;
        }

        IDataConstructor<String, IInst> dataConstructor = DataConstructorFactory
            .getInstConstructor(kiteInsts.get(0).getInstType());
        InstContainerProxy instContainer = InstContainer.ofRequest(orderRequest);
        String prodInstId = prodInst.getProdInstId();
        String newOwnerCustId = prodInst.getNewOwnerCustId();
        for (KiteInst kiteInst : kiteInsts) {
            IInst inst = null;
            if (!dataConstructor.contains(orderRequest, "", kiteInst.getInstId(), null)) {
                inst = dataConstructor.build(orderRequest, kiteInst.getInstId(), null);
            }
            else {
                inst = instContainer.getInst(tableName, kiteInst.getInstId());
            }

            if (AcceptUtils.isAddInst(inst)) {
                inst.setOwnerCustId(newOwnerCustId);
                inst.setNewOwnerCustId(null);
                continue;
            }

            if (Objects.isNull(inst) || StringUtils.isNotBlank(inst.getNewOwnerCustId())
                || KiteStringUtils.equals(newOwnerCustId, inst.getOwnerCustId())) {
                continue;
            }

            if (StringUtils.equalsAny(inst.getActionType(), ActionType.A.name(), ActionType.K.name())) {
                AcceptUtils.setActionType(inst, ActionType.M.name());
            }
            inst.setNewOwnerCustId(newOwnerCustId);

            // 补充newOwnerCustId的变动信息
            AcceptUtils.addInstChange(orderRequest, prodInstId, InstType.PROD_INST, kiteInst.getInstId(),
                kiteInst.getInstType(), ActionType.M, KiteInst.NEW_OWNER_CUST_ID, inst.getOwnerCustId(),
                inst.getNewOwnerCustId());
        }
    }

    /**
     * 功能产品实例属性过户
     * @param orderRequest
     * @param prodInstId
     * @param newOwnerCustId
     */
    private void transferProdInstFuncExts(OrderRequest orderRequest, String prodInstId, String newOwnerCustId) {
        if (Objects.isNull(orderRequest) || StringUtils.isAnyBlank(prodInstId, newOwnerCustId)) {
            return;
        }

        InstContainerProxy instContainer = InstContainer.ofRequest(orderRequest);
        List<ProdInstFunc> prodInstFuncs = instContainer.listProdInstFuncs(prodInstId);
        for (ProdInstFunc prodInstFunc : prodInstFuncs) {
            List<ProdInstFuncExt> prodInstFuncExts = instContainer.listProdInstFuncExts(prodInstFunc.getProdInstId());
            for (ProdInstFuncExt prodInstFuncExt : prodInstFuncExts) {
                if (AcceptUtils.isAddInst(prodInstFuncExt)) {
                    prodInstFuncExt.setOwnerCustId(newOwnerCustId);
                    prodInstFuncExt.setNewOwnerCustId(null);
                    continue;
                }

                if (!KiteStringUtils.equals(newOwnerCustId, prodInstFuncExt.getOwnerCustId())) {
                    prodInstFuncExt.setNewOwnerCustId(newOwnerCustId);
                    if (StringUtils.equalsAny(prodInstFuncExt.getActionType(), ActionType.A.name(),
                        ActionType.K.name())) {
                        AcceptUtils.setActionType(prodInstFuncExt, ActionType.M.name());
                    }
                }
            }
        }
    }

    /**
     * 根据A端产品实例id查询产品实例关系
     * @param aProdInstId
     * @param custId
     * @return
     */
    private List<ProdInstRel> listProdInstRels(String aProdInstId, String custId) {
        if (StringUtils.isAnyBlank(aProdInstId, custId)) {
            return new ArrayList<>();
        }

        Example example = new Example(ProdInstRel.class);
        example.createCriteria().andEqualTo("aProdInstId", aProdInstId).andEqualTo("ownerCustId", custId);
        ProdInstRelMapper mapper = SpringUtil.getBean(ProdInstRelMapper.class);
        List<ProdInstRel> prodInstRels = mapper.selectByExample(example);
        for (ProdInstRel prodInstRel : prodInstRels) {
            if (Objects.equals(ActionType.A.name(), prodInstRel.getActionType())) {
                prodInstRel.setNewActionType(ActionType.K.name());
            }
        }
        return prodInstRels;
    }

    /**
     * 根据产品实例关系创建关系边
     * @param prodInstRel
     * @param sourceInstType
     * @return
     */
    private RelEdge createProdInstRelEdge(ProdInstRel prodInstRel, InstType sourceInstType) {
        if (Objects.isNull(prodInstRel)) {
            return null;
        }

        IRelType relType = RelTypeUtils.getRelType(RelType.PROD_REL_TYPE, prodInstRel.getRelType());
        RelEdge relEdge = new RelEdge();
        relEdge.setSourceInstId(prodInstRel.getaProdInstId());
        relEdge.setSourceInstType(sourceInstType);
        relEdge.setTargetInstId(prodInstRel.getzProdInstId());
        relEdge.setTargetInstType(InstType.PROD_INST);
        relEdge.setRelType(relType);

        return relEdge;
    }
}
